/*
 * Created by kopper on 31.01.15 18:45
 * (C) Copyright 2015 kopperek@gmail.com
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 */

package app.android.kopper.foramemo;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashSet;

import app.android.kopper.foramemo.util.ForaMemoDbHelper;
import app.android.kopper.foramemo.util.LogProxy;
import app.android.kopper.foramemo.util.Word;
import app.android.kopper.foramemo.util.WordGroupDef;

public class CardActivity extends Activity {

    private static final int POOL_SIZE = 10;

    private Button showDefinitionButton;
    private ForaMemoDbHelper dbHelper;
    private Word word;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_card);

        dbHelper = new ForaMemoDbHelper(getApplicationContext());
        word=(Word)getLastNonConfigurationInstance();

        showDefinitionButton = (Button) findViewById(R.id.showDefinitionButton);
        showDefinitionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(word!=null) {
                    Intent foraIntent = new Intent("com.ngc.fora.action.LOOKUP");
                    foraIntent.putExtra("HEADWORD", word.getWord());
                    startActivity(foraIntent);
                }
            }
        });

        //buttons listeners
        int[] buttonsIds=new int[]{
                R.id.result_0,
                R.id.result_1,
                R.id.result_2,
                R.id.result_3,
                R.id.result_4,
                R.id.result_5,
                R.id.rep_result_0,
                R.id.rep_result_1,
        };
        for(int a=0;a<buttonsIds.length;a++)
            findViewById(buttonsIds[a]).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    gotAnswer((Integer.valueOf((String)v.getTag())).intValue());
                }
            });

        showWord(word);
    }

    @Override
    public Object onRetainNonConfigurationInstance() {
        return word;
    }

    private void showWord(Word word) {
        ((TextView)findViewById(R.id.todo)).setText(ForaMemoDbHelper.getStats(dbHelper));
        if(word==null) {
            //gather words
            HashSet<Word> words=new HashSet<>();
            words.addAll(WordGroupDef.getRepWords().getWords(dbHelper,null));
            words.addAll(WordGroupDef.getRepMistakenWords().getWords(dbHelper,null));
            words.addAll(WordGroupDef.getNewMistakenWords().getWords(dbHelper,null));
            int size=words.size();
            LogProxy.d("Scheduled words: "+size);
            int topUpWordsCount=POOL_SIZE-size;
            if(topUpWordsCount>0) { //top up with new
                words.addAll(WordGroupDef.getNewWords().getWords(dbHelper,Long.valueOf(topUpWordsCount)));
            }
            size=words.size();
            LogProxy.d("Available words: "+size);
            if(size==0) {
                finish();
                Toast.makeText(getApplicationContext(),getString(R.string.nothing_more_to_do),Toast.LENGTH_LONG).show();
                return;
            }
            for(;;) {
                word=(Word)words.toArray()[((int)(Math.random()*size))];
                if(size==1||this.word==null||word.getId().longValue()!=this.word.getId().longValue())
                    break;
            }
        }
        this.word=word;
        ((TextView)findViewById(R.id.wordText)).setText(word.getWord());
        //show buttons
        if(word.getNextCalculatedOccurrence()==null) {
            findViewById(R.id.buttonsFirstLayout).setVisibility(View.VISIBLE);
            findViewById(R.id.buttonsRepetitionLayout).setVisibility(View.INVISIBLE);
        } else {
            findViewById(R.id.buttonsFirstLayout).setVisibility(View.INVISIBLE);
            findViewById(R.id.buttonsRepetitionLayout).setVisibility(View.VISIBLE);
        }
    }

    private void gotAnswer(int result) {
        Word w = CardActivity.this.word;
        LogProxy.d("Before: "+w);
        w.setLastAnswer(new Date());
        if(w.getFirstOccurrence()==null)
            w.setFirstOccurrence(new Date());
        LogProxy.d("=>Result: "+result);
        if(w.getNextCalculatedOccurrence() ==null) {//first answer for today
            w.setRepNo(Long.valueOf(w.getRepNo()==null?1:w.getRepNo().longValue()+1));
            //calculate new params
            if(result>=3) {//passed
                if (w.getR1() == null && w.getR2() == null) {
                    w.setR1(Long.valueOf(1));
                } else if (w.getR2()==null) {
                    w.setR2(w.getR1());
                    w.setR1(Long.valueOf(6));
                } else {
                    w.setR1(w.getEp().multiply(new BigDecimal(w.getR1())).setScale(0, RoundingMode.HALF_UP).longValue());
                }
                markWordPassed(w, w.getR1());
            } else {
                w.setR1(Long.valueOf(1));
                w.setR2(null);
                w.setNextCalculatedOccurrence(w.getR1());
            }
            BigDecimal newEp = w.getEp().add(BigDecimal.valueOf(0.1 - (5 - result) * (0.08 + (5 - result) * 0.02)));
            if(newEp.compareTo(new BigDecimal("1.3"))<0)
                newEp=new BigDecimal("1.3"); //todo: sprawdzic
            w.setEp(newEp);
        } else { //next answer
            if(result==5) { //passed
                markWordPassed(w, w.getNextCalculatedOccurrence());
            }
        }
        LogProxy.d("After: "+w);
        w.save(dbHelper);
        showWord(null);
    }

    private void markWordPassed(Word w, Long period) {
        try {
            Date nextOccurrence = new Date(new Date().getTime() + period.longValue() * 24 * 60 * 60 * 1000);
            w.setNextOccurrence(nextOccurrence);
            w.setNextCalculatedOccurrence(null);
        } catch (Exception e) {
            LogProxy.e("", e);
        }
    }
}
